
<!DOCTYPE html
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml">
   <head>
      <meta charset="utf-8"></meta>
      <meta name="viewport" content="width=device-width, initial-scale=1.0"></meta>
      <title>Chapter&nbsp;14.&nbsp;Virtual Nodes &amp; Relationships (Graph Projections) - APOC User Guide 3.4</title>
      <link rel="stylesheet" type="text/css" href="../docbook.css"></link>
      <link rel="stylesheet" type="text/css" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"></link>
      <link rel="stylesheet" type="text/css" href="//cdn.datatables.net/1.10.13/css/jquery.dataTables.min.css"></link>
      <link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/font-awesome/4.1.0/css/font-awesome.min.css"></link>
      <link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/css?family=Open+Sans:400,300,400italic,600,300italic"></link>
      <link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/codemirror/5.11.0/codemirror.min.css"></link>
      <link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/codemirror/5.11.0/theme/neo.min.css"></link>
      <link rel="stylesheet" type="text/css" href="../css/chunked-base.css"></link>
      <link rel="stylesheet" type="text/css" href="../css/extra.css"></link><script src="//code.jquery.com/jquery-1.12.4.js" type="text/javascript"></script><script src="//cdn.datatables.net/1.10.13/js/jquery.dataTables.min.js" type="text/javascript"></script><script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" type="text/javascript"></script><script src="//cdnjs.cloudflare.com/ajax/libs/codemirror/5.11.0/codemirror.min.js" type="text/javascript"></script><script src="//cdnjs.cloudflare.com/ajax/libs/codemirror/5.11.0/addon/runmode/runmode.min.js" type="text/javascript"></script><script src="//cdnjs.cloudflare.com/ajax/libs/codemirror/5.11.0/mode/cypher/cypher.min.js" type="text/javascript"></script><script src="../javascript/datatable.js" type="text/javascript"></script><script src="../javascript/colorize.js" type="text/javascript"></script><script src="../javascript/tabs-for-chunked.js" type="text/javascript"></script><script src="../javascript/mp-nav.js" type="text/javascript"></script><script src="../javascript/versionswitcher.js" type="text/javascript"></script><script src="../javascript/version.js" type="text/javascript"></script><script src="//s3-eu-west-1.amazonaws.com/alpha.neohq.net/docs/new-manual/assets/search.js" type="text/javascript"></script><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"></meta>
      <link rel="prev" href="../cypher-execution/cypher-based-procedures-functions/" title="13.6.&nbsp;Custom, Cypher Based Procedures and Functions"></link>
      <link rel="next" href="virtual-nodes-rels/" title="14.2.&nbsp;Virtual Nodes/Rels"></link>
      <link rel="shortcut icon" href="https://neo4j.com/wp-content/themes/neo4jweb/favicon.ico"></link><script>
        $(document).ready(function() {
          CodeMirror.colorize();
          tabTheSource($('body'));
          var $header = $('header').first();
          $header.prepend(
            $('<a href="" id="logo"><img src="https://neo4j.com/wp-content/themes/neo4jweb/assets/images/neo4j-logo-2015.png" alt="Neo4j Logo"></img></a>')
          );
          var $sidebar = $('<div id="sidebar-wrapper"></div>');
          $.get('toc.html', function (d){
            $(d).appendTo($sidebar);
            highlightToc();
            highlightLibraryHeader();
          });
          $sidebar.insertAfter($('header').first());
        });
        </script></head>
   <body>
      <header>
         <div class="searchbox">
            <form id="search-form" class="search" name="search-form" role="search"><input id="search-form-input" name="q" title="search" type="search" lang="en" placeholder="Search Neo4j docs..." aria-label="Search Neo4j documentation" max-length="128" required="required"></input><input id="search-form-button" type="submit" value="Search"></input></form>
         </div>
         <ul class="documentation-library">
            <li><a href="https://neo4j.com/docs/operations-manual/current">Operations Manual</a></li>
            <li><a href="https://neo4j.com/docs/developer-manual/current/">Developer Manual</a></li>
            <li><a href="https://neo4j.com/docs/ogm-manual/current/">OGM Manual</a></li>
            <li><a href="https://neo4j.com/docs/graph-algorithms/current/">Graph Algorithms</a></li>
            <li><a href="https://neo4j-contrib.github.io/neo4j-apoc-procedures/3.4/">APOC</a></li>
            <li><a href="https://neo4j.com/docs/java-reference/current/">Java Reference</a></li>
         </ul>
         <nav id="header-nav"><span class="nav-previous"><a accesskey="p" href="../cypher-execution/cypher-based-procedures-functions/"><span class="fa fa-long-arrow-left" aria-hidden="true"></span>Custom, Cypher Based Procedures and Functions</a></span><span class="nav-current">
               <p class="nav-title hidden">Chapter&nbsp;14.&nbsp;Virtual Nodes &amp; Relationships (Graph Projections)</p></span><span class="nav-next"><a accesskey="n" href="virtual-nodes-rels/">Virtual Nodes/Rels<span class="fa fa-long-arrow-right" aria-hidden="true"></span></a></span></nav>
      </header>
      <div id="search-results" class="hidden"></div>
      <section class="chapter" id="virtual">
         <div class="titlepage">
            <div>
               <div>
                  <h1 class="title">Chapter&nbsp;14.&nbsp;Virtual Nodes &amp; Relationships (Graph Projections)</h1>
               </div>
            </div>
         </div>
         <p>Virtual Nodes and Relationships don&#8217;t exist in the graph, they are only returned to the UI/user for representing a graph projection.
            They can be visualized or processed otherwise.
            Please note that they have negative id&#8217;s.
         </p>
         <section class="section" id="_use_cases">
            <div class="titlepage">
               <div>
                  <div>
                     <h2 class="title" style="clear: both"><a class="anchor" href="#_use_cases"></a>14.1.&nbsp;Use Cases
                     </h2>
                  </div>
               </div>
            </div>
            <p>Virtual nodes and relationships are used for quite a number of things.</p>
            <p>You can create visual <span class="strong"><strong>representation of data that are not in the graph</strong></span>, e.g. from other databases, that&#8217;s also what the <code class="literal">apoc.bolt.load</code> procedure supports.
            </p>
            <p>Also the virtual nodes and relationships are used by <code class="literal">db.schema</code> and <code class="literal">apoc.meta.graph</code></p>
            <p>You can use it to <span class="strong"><strong>visually project data</strong></span>, e.g. aggregate relationships into one, or collapse intermediate nodes into virtual relationships etc.
               For instance, you can project a citation graph into a virtual author-author or paper-paper graph with aggregated relationships
               between them.
               Or turn Twitter data into an user-user mention graph.
            </p>
            <p>This is already automated in <code class="literal">apoc.nodes.group</code> which automatically groups nodes and relationships by grouping properties, [read more about that here](<a class="link" href="https://neo4j.com/blog/apoc-release-for-neo4j-3-4-with-graph-grouping/" target="_top">https://neo4j.com/blog/apoc-release-for-neo4j-3-4-with-graph-grouping/</a>).
            </p>
            <p>You can <span class="strong"><strong>combine</strong></span> real and virtual entities, e.g. connecting two real nodes with a virtual relationship or connecting a virtual node via a
               virtual relationship to a real node.
            </p>
            <p>APOC has already some means to also create "virtual graphs" which can also be used for export.</p>
            <p>Some more uses of virtual entities:</p>
            <div class="itemizedlist">
               <ul class="itemizedlist" style="list-style-type: disc; ">
                  <li class="listitem">return only a few properties of nodes/rels to the visualization, e.g. of you have huge text properties</li>
                  <li class="listitem">visualize clusters found by graph algorithms</li>
                  <li class="listitem">aggregate information to a higher level of abstraction</li>
                  <li class="listitem">skip intermediate nodes in a longer path</li>
                  <li class="listitem">hide away properties or intermediate nodes/relationships for security reasons</li>
                  <li class="listitem">graph grouping</li>
                  <li class="listitem">visualization of data from other sources (computation, RDBMS, document-dbs, CSV, XML, JSON) as graph without even storing
                     it
                  </li>
                  <li class="listitem">projecting partial data</li>
               </ul>
            </div>
            <p>You can also create them yourself e.g. for projections.</p>
            <p>One thing to keep in mind: as you cannot look up already created virtual nodes from the graph you have to keep them in your
               own lookup structure.
               Something that works well for it is <code class="literal">apoc.map.groupBy</code> which creates a map from a list of entities, keyed by the string value of a given property.
            </p>
            <p>Virtual entities so far work across all surfaces, Neo4j-Browser, Bloom, neovis, and all the drivers, which is really cool,
               even if it was not originally intended.
            </p>
            <p>They are mainly used for visualization but Cypher itself can&#8217;t access them (their ids, labels, types, properties)
               That&#8217;s why we added a number of functions to access their properties, labels, and rel-types.
            </p>
            <p>In some future, they might be subsumed by graph views, the ability to return graphs and composable Cypher queries in Cypher
               10.
            </p>
            <div class="admonitionblock note">
               <table>
                  <tbody>
                     <tr>
                        <td class="icon"><i class="fa icon-note" title="note"></i></td>
                        <td class="content">
                           <p>We also allow graph projections to be used [as inputs for graph algorithms](<a class="link" href="https://neo4j.com/docs/graph-algorithms/current/introduction/#cypher-projection" target="_top">https://neo4j.com/docs/graph-algorithms/current/introduction/#cypher-projection</a>), so you don&#8217;t actually have to change your data to run an algorithm on a different shape but you can just specify node-
                              and relationship-lists with two Cypher statements.
                              You can visualize (a subset of) those using virtual nodes and relationships too.
                           </p>
                        </td>
                     </tr>
                  </tbody>
               </table>
            </div>
         </section>
         <section class="section" id="_nodes_collapse">
            <div class="titlepage">
               <div>
                  <div>
                     <h2 class="title" style="clear: both"><a class="anchor" href="#_nodes_collapse"></a>14.3.&nbsp;Nodes collapse
                     </h2>
                  </div>
               </div>
            </div>
            <div class="informaltable">
               <div class="table" id="d0e17703">
                  <table class="informaltable" border="1">
                     <colgroup>
                        <col class="col_1"></col>
                        <col class="col_2"></col>
                     </colgroup>
                     <tbody>
                        <tr>
                           <td style="text-align: left; vertical-align: top; ">
                              <p><code class="literal">apoc.nodes.collapse([&lt;node&gt;], {config})</code></p>
                           </td>
                           <td style="text-align: left; vertical-align: top; ">
                              <p>returns the list of nodes merged into a VirtualNode</p>
                           </td>
                        </tr>
                     </tbody>
                  </table>
               </div>
            </div>
            <section class="section" id="_config_3">
               <div class="titlepage">
                  <div>
                     <div>
                        <h3 class="title"><a class="anchor" href="#_config_3"></a>14.3.1.&nbsp;Config:
                        </h3>
                     </div>
                  </div>
               </div>
               <p>On <code class="literal">apoc.nodes.collapse</code> with config properties you can choose from 3 different behavior:
               </p>
               <div class="itemizedlist">
                  <ul class="itemizedlist" style="list-style-type: disc; ">
                     <li class="listitem">"properties": "overwrite" : if there is the same property in more node, in the new one will have the last relationship&#8217;s/node&#8217;s
                        property value
                     </li>
                     <li class="listitem">"properties": "discard" : if there is the same property in more node, the new one will have the first relationship&#8217;s/node&#8217;s
                        property value
                     </li>
                     <li class="listitem">"properties": "combine" : if there is the same property in more node, the new one a value&#8217;s array with all relationship&#8217;s/node&#8217;s
                        values
                     </li>
                  </ul>
               </div>
               <p>If properties parameter isn&#8217;t set relationships properties are <code class="literal">discard</code>.
               </p>
               <div class="itemizedlist">
                  <ul class="itemizedlist" style="list-style-type: disc; ">
                     <li class="listitem">"mergeVirtualRels: true/false" : give the possibility to merge relationships with same type and direction. (DEFAULT <code class="literal">true</code>)
                     </li>
                     <li class="listitem">"selfRel: true/false" : give the possibility to create the self relationship. (DEFAULT <code class="literal">false</code>)
                     </li>
                     <li class="listitem">"countMerge: true/false" : give the possibility count all the Nodes/Relationships merged. (DEFAULT <code class="literal">true</code>)
                     </li>
                     <li class="listitem">"collapsedLabel: true/false" : give the possibility to add the label <code class="literal">:Collapsed</code> to the virtualNode. (DEFAULT <code class="literal">false</code>)
                     </li>
                  </ul>
               </div>
            </section>
         </section>
         <section class="section" id="_nodes_collapse_example">
            <div class="titlepage">
               <div>
                  <div>
                     <h2 class="title" style="clear: both"><a class="anchor" href="#_nodes_collapse_example"></a>14.4.&nbsp;Nodes collapse example
                     </h2>
                  </div>
               </div>
            </div>
            <p>With this dataset we have:</p>
            <div class="informalfigure">
               <div class="mediaobject"><img src="https://raw.githubusercontent.com/neo4j-contrib/neo4j-apoc-procedures/3.4/docs/images/apoc.nodes.collapse_1.png" width="600" alt="apoc.nodes.collapse 1"></img></div>
            </div>
            <p>If we want to collapse the people living in the city to a single node, we pass them to the procedure.</p><pre class="programlisting highlight"><code data-lang="cypher">MATCH (p:Person)-[:LIVES_IN]-&gt;(c:City)
WITH c, collect(p) as subgraph
CALL apoc.nodes.collapse(subgraph,{properties:'combine'}) yield from, rel, to
return from, rel, to</code></pre><p>And get this result:</p>
            <div class="informalfigure">
               <div class="mediaobject"><img src="https://raw.githubusercontent.com/neo4j-contrib/neo4j-apoc-procedures/3.4/docs/images/apoc.nodes.collapse_2.png" width="600" alt="apoc.nodes.collapse 2"></img></div>
            </div>
            <p>With this dataset we have:</p>
            <div class="informalfigure">
               <div class="mediaobject"><img src="https://raw.githubusercontent.com/neo4j-contrib/neo4j-apoc-procedures/3.4/docs/images/apoc.nodes.collapse_3.png" width="600" alt="apoc.nodes.collapse 3"></img></div>
            </div>
            <p>If we also want to collapse them onto the city itself, we add the city node <span class="emphasis"><em>first</em></span> to the collection.
            </p><pre class="programlisting highlight"><code data-lang="cypher">MATCH (p:Person)-[:LIVES_IN]-&gt;(c:City)
WITH c, c + collect(p) as subgraph
CALL apoc.nodes.collapse(subgraph) yield from, rel, to
return from, rel, to</code></pre><p>And get this result:</p>
            <div class="informalfigure">
               <div class="mediaobject"><img src="https://raw.githubusercontent.com/neo4j-contrib/neo4j-apoc-procedures/3.4/docs/images/apoc.nodes.collapse_4.png" width="600" alt="apoc.nodes.collapse 4"></img></div>
            </div>
         </section>
      </section>
      <footer><script type="text/javascript">
          (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
            (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
          m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
          })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
          //Allow Linker
          ga('create', 'UA-1192232-34','auto', {'allowLinker': true});
          ga('send', 'pageview');
          // Load the plugin.
          ga('require', 'linker');
          // Define which domains to autoLink.
          ga('linker:autoLink', ['neo4j.org','neo4j.com','neotechnology.com','graphdatabases.com','graphconnect.com']);
        </script><script type="text/javascript">
          document.write(unescape("%3Cscript src='//munchkin.marketo.net/munchkin.js' type='text/javascript'%3E%3C/script%3E"));
        </script><script>Munchkin.init('773-GON-065');</script></footer>
   </body>
</html>